#ifndef GENERIK_ANY_H
#define GENERIK_ANY_H

#include <string>
#include <sstream>
#include <typeinfo> 

#include "tracing.h"

namespace generik
{
	
	/*
	******** convert *********
	*/
	
	template <typename TYPEOUT, typename TYPEIN>
	TYPEOUT convert(const TYPEIN& value)
	{
		std::stringstream ss;
		ss<<value;
		TYPEOUT result;
		ss>>result;
		return result;
	}
	
	template <>
	std::string convert<std::string, std::string>(const std::string& value)
	{
		return value;
	}
	
	/*
	template <typename TYPE>
	std::string convert(const TYPE& value)
	{
		std::stringstream ss;
		ss<<value;
		return ss.str();
	}
	*/
	
	template <>
	std::string convert<std::string>(const bool& value)
	{
		if (value) return "true"; else return "false";
	}
	
	/*
	template <typename TYPE>
	TYPE convert(const std::string& value)
	{
		std::stringstream ss;
		ss<<value;
		TYPE result;
		ss>>result;
		return result;
	}
	*/
	/*
	template <>
	std::string convert<std::string>(const std::string& value)
	{
		return value;
	}
	*/
	
	template <>
	bool convert<bool>(const std::string& value)
	{
		if (value.empty()) return false;
		if (value == "false") return false;
		if (value == "0") return false;
		return true;
	}
	
	template <>
	int convert<int>(const std::string& value)
	{
		return atoi(value.c_str());
	}
	
	template <>
	double convert<double>(const std::string& value)
	{
		return atof(value.c_str());
	}
	
	/*
	******** any_value interface *********
	*/
	
	struct any_value
	{
		virtual any_value* copy() = 0;
		virtual void set(const std::string& value) = 0;
		virtual void set() = 0;
		virtual std::string get() = 0;
		virtual ~any_value() {}
	};
	
	/*
	******** any_ templates *********
	*/
	
	template <typename TYPE>
	struct any_
	: any_value
	{
		TYPE* _target;
		
		any_(TYPE* target)
		: _target(target)
		{
			GENERIK_TRACER;
		}
		
		any_value* copy()
		{
			any_<TYPE>* instance = new any_<TYPE>(_target);
			return instance;
		}
		
		void set()
		{
			(*_target) = TYPE();
		}
		void set(const std::string& value)
		{
			(*_target) = convert<TYPE>(value);
		}
		std::string get()
		{
			return convert<std::string>(*_target);
		}
		virtual ~any_()
		{
			GENERIK_TRACER;
		}
	};

	template <>
	struct any_<bool>
	: any_value
	{
		bool* _target;
		
		any_(bool* target)
		: _target(target)
		{
			GENERIK_TRACER;
		}
		
		any_value* copy()
		{
			any_<bool>* instance = new any_<bool>(_target);
			return instance;
		}
		
		void set()
		{
			(*_target) = false;
		}
		void set(const std::string& value)
		{
			(*_target) = convert<bool>(value);
		}
		std::string get()
		{
			return convert<std::string, bool>(*_target);
		}
		virtual ~any_()
		{
			GENERIK_TRACER;
		}
	};
	
	/*
	******** any class *********
	*/
	
	struct any
	{
		any_value* _value;
		
		template <typename TYPE>
		any(TYPE* target)
		: _value(0)
		{
			GENERIK_TRACER;
			std::cout<<"creating new any_value of type "<<typeid(target).name()<<std::endl;
			_value = new any_<TYPE>(target);
		}
		any(const any& a_in)
		: _value(a_in._value->copy())
		{
			GENERIK_TRACER;
		}
		void set(const std::string& value)
		{
			_value->set(value);
		}
		void set()
		{
			_value->set();
		}
		std::string get()
		{
			return _value->get();
		}
		~any()
		{
			GENERIK_TRACER;
			delete _value;
		}
	};
	
	
}

#endif


